﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Checksums;

namespace Aspfm.Dal
{
    /// <summary>   
    /// 适用与ZIP压缩   
    /// </summary>   
    public class ZipHelper
    {

        public static string ZipFile(string strFileOrDirectory, string strZip, string password = null)
        {
            string errmsg = "";

            ZipOutputStream s = null;
            try
            {
                s = new ZipOutputStream(File.Create(strZip));
                if (!string.IsNullOrEmpty(password)) s.Password = password;
                s.SetLevel(6); // 0 - store only to 9 - means best compression
                if (File.Exists(strFileOrDirectory))
                {
                    ZipFile(s, strFileOrDirectory,  strFileOrDirectory);
                }
                else if (Directory.Exists(strFileOrDirectory))
                {
                    if (strFileOrDirectory[strFileOrDirectory.Length - 1] != Path.DirectorySeparatorChar)
                        strFileOrDirectory += Path.DirectorySeparatorChar;
                    zip(strFileOrDirectory, s, strFileOrDirectory);
                }
            }
            catch (Exception ex)
            {
                errmsg = ex.Message + ex.StackTrace;
            }
            finally
            {
                if (s != null)
                {
                    s.Finish();
                    s.Close();
                }
            }
            return errmsg;
        }


        private static void zip(string strFile, ZipOutputStream s, string staticFile)
        {
            if (strFile[strFile.Length - 1] != Path.DirectorySeparatorChar) strFile += Path.DirectorySeparatorChar;
            //Crc32 crc = new Crc32();
            string[] filenames = Directory.GetFileSystemEntries(strFile);
            foreach (string file in filenames)
            {

                if (Directory.Exists(file))
                {
                    zip(file, s, staticFile);
                }

                else // 否则直接压缩文件
                {
                    //打开压缩文件
                    ZipFile(s, staticFile,  file);
                }
            }
        }

        private static void ZipFile(ZipOutputStream s, string staticFile,  string file)
        {
            //if (crc == null)
            //{
            //    crc = new Crc32();
            //}

            FileStream fs = null;
            try
            {
                fs = File.OpenRead(file);

                byte[] buffer = new byte[fs.Length];
                fs.Read(buffer, 0, buffer.Length);
                string tempfile = file.Substring(staticFile.LastIndexOf("\\") + 1);
                ZipEntry entry = new ZipEntry(tempfile);

                entry.DateTime = DateTime.Now;
                entry.Size = fs.Length;
                fs.Close();
                //crc.Reset();
                //crc.Update(buffer);
                //entry.Crc = crc.Value;
                s.PutNextEntry(entry);

                s.Write(buffer, 0, buffer.Length);
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Flush();
                    fs.Close();
                }
            }
        }

        public static string unZipFile(string TargetFile, string fileDir, string password = null,bool isAspfm=false)
        {
            string errmsg = "";
            ZipInputStream s = null;
            FileStream streamWriter = null;
            try
            {
                //读取压缩文件(zip文件)，准备解压缩
                s = new ZipInputStream(File.OpenRead(TargetFile.Trim()));
                if (!string.IsNullOrEmpty(password)) s.Password = password;
                ZipEntry theEntry;
                string path = fileDir;
                //解压出来的文件保存的路径

                string rootDir = " ";
                //根目录下的第一个子文件夹的名称
                while ((theEntry = s.GetNextEntry()) != null)
                {
                    rootDir = Path.GetDirectoryName(theEntry.Name);
                    //得到根目录下的第一级子文件夹的名称
                    if (rootDir.IndexOf("\\") >= 0)
                    {
                        rootDir = rootDir.Substring(0, rootDir.IndexOf("\\") + 1);
                    }
                    string dir = Path.GetDirectoryName(theEntry.Name);
                    //根目录下的第一级子文件夹的下的文件夹的名称
                    string fileName = Path.GetFileName(theEntry.Name);
                    if (isAspfm)
                    {
                        fileName = Path.GetFileName(TargetFile);
                    }
                    //根目录下的文件名称
                    if (dir != " ")
                    //创建根目录下的子文件夹,不限制级别
                    {
                        if (!Directory.Exists(fileDir + "\\" + dir))
                        {
                            path = fileDir + "\\" + dir;
                            //在指定的路径创建文件夹
                            Directory.CreateDirectory(path);
                        }
                    }

                    //以下为解压缩zip文件的基本步骤
                    //基本思路就是遍历压缩文件里的所有文件，创建一个相同的文件。
                    if (fileName != String.Empty)
                    {
                        streamWriter = File.Create(fileDir + "\\" + theEntry.Name);

                        int size = 2048;
                        byte[] data = new byte[2048];
                        while (true)
                        {
                            size = s.Read(data, 0, data.Length);
                            if (size > 0)
                            {
                                streamWriter.Write(data, 0, size);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }
                //if (rootDir == " ")
                //{
                //    errmsg = "not_file_in_zip";
                //}
            }
            catch (Exception ex)
            {
                errmsg = ex.Message + ex.StackTrace;
            }
            finally
            {
                if (s != null)
                {
                    s.Close();
                    s.Dispose();
                }
                if (streamWriter != null)
                {
                    streamWriter.Close();
                    streamWriter.Dispose();
                }
            }
            return errmsg;
        }
    }
}